#ifndef __UTIL_H__
#define __UTIL_H__
#include <string>
#include <vector>
#include <sstream>
#include <algorithm>
#include <time.h>
#include <sys/time.h>
#include <json.h>

class CTools
{
    public:
        static int64_t GetTickCount()
        {
            timeval timesnow;
            struct timezone tmpzone;
            gettimeofday(&timesnow,&tmpzone);
            return ((int64_t)(timesnow.tv_sec*1000) + (int64_t)(timesnow.tv_usec/1000));
        }

        static uint64_t GetUnixTime()
        {
            timeval timesnow;
            struct timezone tmpzone;
            gettimeofday(&timesnow,&tmpzone);
            return timesnow.tv_sec;
        }

        static uint64_t GetUnixTimeMs()
        {
            timeval timesnow;
            gettimeofday(&timesnow, NULL);
            return (timesnow.tv_sec * 1000000 + timesnow.tv_usec);
        }

        static int64_t GetUnixTimeNs() {
            timeval timesnow;
            gettimeofday(&timesnow, NULL);
            return (timesnow.tv_sec * 1000LL + timesnow.tv_usec / 1000LL);
        }
		
		static int GetDateStr(std::string &str)
		{
			char now[64] = {0};
			time_t tt = time(NULL);
			struct tm *ttime;
			ttime = localtime(&tt);
			strftime(now, sizeof(now), "%Y%m%d", ttime);
            str = now;
			return 0;
		}

        static int split_str(const char* ps_str, char* ps_sp, vector<std::string> &v_ret)
        {
            char* ps_temp;
            char* p;
            int i_len = (int)strlen(ps_str);
            std::string st_str;
            ps_temp = new char[i_len + 2];
            snprintf(ps_temp, i_len + 1, "%s", ps_str);
            char *last = NULL;    p = strtok_r(ps_temp, ps_sp, &last);
            if (NULL == p)
            {
                delete ps_temp;
                return 0;
            }
            st_str = (std::string)p;
            v_ret.push_back(st_str);
            while (NULL != (p = strtok_r(NULL, ps_sp, &last)))
            {
                st_str = (std::string)p;
                v_ret.push_back(st_str);
            }
            delete ps_temp;
            return 0;
        }

        static bool isSameDay(time_t time1, time_t time2)
        {
            return (((time1 + 28800) / 86400) == ((time2 + 28800) / 86400));
        }

        static bool isSameWeek(time_t time1, time_t time2)
        {
            std::tm* local_tm = std::localtime(&time1);
            int week1 = local_tm->tm_wday == 0 ?7:local_tm->tm_wday;
            int year_week1 = local_tm->tm_year + ((local_tm->tm_yday + 1) + 6 - week1) / 7;
            local_tm = std::localtime(&time2);
            int week2 = local_tm->tm_wday == 0 ?7:local_tm->tm_wday;
            int year_week2 = local_tm->tm_year + ((local_tm->tm_yday + 1) + 6 - week2) / 7;
            return year_week1 == year_week2;
        }
        
        static std::map<std::string, std::string> ParseUrlParams(std::string params_str)
        {
            std::map<std::string, std::string> params;

            char* s = (char*)params_str.c_str();
            char* e = s + params_str.size();
            char* p = s;
            char* key_s = s;
            char* key_e = s;
            char* val_s = s;
            char* val_e = s;
            char word = '&';
            char sep = '=';
            while (p <= e)
            {
                if (p == e)
                {
                    if (key_s != val_s)
                    {
                        val_e = p;
                        params[std::string(key_s, key_e - key_s)] = std::string(val_s, val_e - val_s);
                    }

                    break;
                }
                else if (*p == word)
                {
                    if (key_s != val_s)
                    {
                        val_e = p;
                        params[std::string(key_s, key_e - key_s)] = std::string(val_s, val_e - val_s);
                    }

                    // 重置区间
                    key_s = key_e = val_s = val_e = p + 1;
                }
                else if (*p == sep)
                {
                    key_e = p;
                    val_s = p + 1;
                }
                else
                {
                    // 
                }
                p++;
            }

            return params;
        }

        static std::string ToStr(const Json::Value& msg)
        {
            Json::FastWriter writer;
            writer.omitEndingLineFeed();
            return writer.write(msg);
        }

        static bool FromStr(Json::Value& msg, const std::string& json_string)
        {
            Json::Reader reader;
            return reader.parse(json_string, msg);
        }
        
        template<typename T>
        static std::string ToString(const std::vector<T>& group, const std::string& sep = ",")
        {
            std::stringstream ss;
            for (int i = 0; i < group.size(); i++)
            {
                if (i != 0) ss << sep;
                ss << group[i];
            }
            return ss.str();
        }

        template<typename T>
        static std::string ToMapString(const T& group, const std::string& kv_sep = ":", const std::string& item_sep = ",")
        {
            std::stringstream ss;
            bool is_first = true;
            for (auto& item : group)
            {
                if (is_first)
                {
                    is_first = false;
                }
                else
                {
                    ss << item_sep;
                }
                ss << item.first << kv_sep << item.second;
            }
            return ss.str();
        }
};

#endif